package com.sc.security.service.impl;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.sc.security.dao.SysAclMapper;
import com.sc.security.dao.SysAclModuleMapper;
import com.sc.security.dao.SysDeptMapper;
import com.sc.security.dao.SysRoleMapper;
import com.sc.security.dto.AclDto;
import com.sc.security.dto.AclModuleDto;
import com.sc.security.dto.DeptLevelDto;
import com.sc.security.dto.RoleDto;
import com.sc.security.model.SysAcl;
import com.sc.security.model.SysAclModule;
import com.sc.security.model.SysDept;
import com.sc.security.model.SysRole;
import com.sc.security.service.SysCoreService;
import com.sc.security.service.TreeService;
import com.sc.security.utils.LevelUtil;
import com.sc.security.utils.StringUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.acl.Acl;
import java.util.*;
import java.util.stream.Collectors;

/***
 * 部门树结构
 */
@Service
public class TreeServiceImpl implements TreeService {

    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private SysAclModuleMapper aclModuleMapper;
    @Autowired
    private SysRoleMapper roleMapper;
    @Autowired
    private SysCoreService coreService;
    @Autowired
    private SysAclMapper aclMapper;

    /***
     * DEPT
     * 首先取出数据，做一下简单封装
     * @return
     */
    @Override
    public List<DeptLevelDto> deptTree() {
        List<SysDept> depts = deptMapper.getAllDept();
        List<DeptLevelDto> deptLevelDtos = Lists.newArrayList();
        for (SysDept dept:depts){
            DeptLevelDto dto = DeptLevelDto.adapt(dept);
            deptLevelDtos.add(dto);
        }
        return deptListToTree(deptLevelDtos);
    }
    /***
     * 处理根层数据，按照从小到大顺序进行排序
     * @param dtoList
     * @return
     */
    private List<DeptLevelDto> deptListToTree(List<DeptLevelDto> dtoList) {
        if(CollectionUtils.isEmpty(dtoList)){
            return Lists.newArrayList();
        }
        Multimap<String,DeptLevelDto> levelDeptMap = ArrayListMultimap.create();
        List<DeptLevelDto> root = Lists.newArrayList();
        for(DeptLevelDto d:dtoList){
            levelDeptMap.put(d.getLevel(),d);
            if(LevelUtil.ROOT.equals(d.getLevel())){
                root.add(d);
            }
        }
        //按照seq排序
        Collections.sort(root, new Comparator<DeptLevelDto>() {
            @Override
            public int compare(DeptLevelDto o1, DeptLevelDto o2) {
                return o1.getSeq()-o2.getSeq();
            }
        });
        //递归
        transformDeptTree(root,LevelUtil.ROOT,levelDeptMap);
        return root;
    }
    /***
     * 递归处理每一层数据
     * @param deptLevelDtos
     * @param level
     * @param levelDeptMap
     */
    private   void transformDeptTree(List<DeptLevelDto> deptLevelDtos,String level,Multimap<String,DeptLevelDto> levelDeptMap){
        for(int i=0;i<deptLevelDtos.size();i++){
            //遍历该层每个元素
            DeptLevelDto deptLevelDto = deptLevelDtos.get(i);
            //处理当前层级的数据
            String nextLevel = LevelUtil.calculateLevel(level,deptLevelDto.getId());
            //处理下一层
            List<DeptLevelDto> list = (List<DeptLevelDto>) levelDeptMap.get(nextLevel);
            if(CollectionUtils.isNotEmpty(list)){
                //排序
                Collections.sort(list,deptSeqComparator);
                //设置下一层部门
                deptLevelDto.setDeptList(list);
                //进入下一层处理
                transformDeptTree(list,nextLevel,levelDeptMap);
            }
        }
    }
    private Comparator<DeptLevelDto> deptSeqComparator = new Comparator<DeptLevelDto>() {
        @Override
        public int compare(DeptLevelDto o1, DeptLevelDto o2) {
            return o1.getSeq()-o2.getSeq();
        }
    };

    /***
     * ROLE
     * @param roleId
     * @return
     */
    @Override
    public List<AclModuleDto> roleTree(Integer roleId) {
        //1.当前用户分配的权限点
        List<SysAcl> userAclList = coreService.getCurrentUserAclList();
        //2.当前角色分配的权限点
        List<SysAcl> roleAclList =  coreService.getRoleAclList(roleId);
        //3.系统所有权限点
        List<AclDto> dtos = Lists.newArrayList();


        Set<Integer> userAclIdSet = userAclList.stream().map(sysAcl->sysAcl.getId()).collect(Collectors.toSet());
        Set<Integer> roleAclIdSet = roleAclList.stream().map(sysAcl->sysAcl.getId()).collect(Collectors.toSet());


        List<SysAcl> allAcl = aclMapper.getAll();
        for (SysAcl sysAcl:allAcl){
            AclDto dto = AclDto.adapt(sysAcl);
            if(userAclIdSet.contains(sysAcl.getId())){
                dto.setHasAcl(true);
            }
            if(roleAclIdSet.contains(sysAcl.getId())){
                dto.setChecked(true);
            }
            dtos.add(dto);
        }
        return aclList2Tree(dtos);
    }


    private List<AclModuleDto> aclList2Tree(List<AclDto> dtos){
        if(CollectionUtils.isEmpty(dtos)){
            return Lists.newArrayList();
        }
        List<AclModuleDto> aclModuleDtoList = aclTree();
        Multimap<Integer,AclDto> map = ArrayListMultimap.create();
        for(AclDto acl: dtos ){
            if(acl.getStatus()==1){
                map.put(acl.getAclModuleId(),acl);
            }
        }
        bindAclsWithOrder(aclModuleDtoList,map);
        return aclModuleDtoList;
    }
    private void bindAclsWithOrder(List<AclModuleDto> aclModuleDtoList,Multimap<Integer,AclDto> map){
            if(CollectionUtils.isEmpty(aclModuleDtoList)){
                return;
            }
            for(AclModuleDto dto:aclModuleDtoList){
                List<AclDto> aclDtoList = (List<AclDto>) map.get(dto.getId());
                if(CollectionUtils.isNotEmpty(aclDtoList)){
                    Collections.sort(aclDtoList, new Comparator<AclDto>() {
                        @Override
                        public int compare(AclDto o1, AclDto o2) {
                           return o1.getId()-o2.getId();
                        }
                    });
                    dto.setAclList(aclDtoList);
                }
                bindAclsWithOrder(dto.getAclModuleList(),map);
            }
    }

    /**
     * ACLModule
     * 取出数据，简单封装
     * @return
     */
    @Override
    public List<AclModuleDto> aclTree() {
        List<SysAclModule> modules = aclModuleMapper.getAllAcl();
        List<AclModuleDto> aclModuleDtos = Lists.newArrayList();
        for (SysAclModule module:modules){
            AclModuleDto dto = AclModuleDto.adapt(module);
            aclModuleDtos.add(dto);
        }
        return aclListToTree(aclModuleDtos);
    }
    private List<AclModuleDto> aclListToTree(List<AclModuleDto> aclModuleDtos) {
        if(CollectionUtils.isEmpty(aclModuleDtos)){
            return Lists.newArrayList();
        }
        Multimap<String,AclModuleDto> levelMap  =  ArrayListMultimap.create();
        List<AclModuleDto> root = Lists.newArrayList();
        for(AclModuleDto d : aclModuleDtos){
            levelMap.put(d.getLevel(),d);
            if(LevelUtil.ROOT.equals(d.getLevel())){
                root.add(d);
            }
        }
        Collections.sort(root, new Comparator<AclModuleDto>() {
            @Override
            public int compare(AclModuleDto o1, AclModuleDto o2) {
                return o1.getSeq()-o2.getSeq();
            }
        });
        //递归
        aclTransformTree(root,LevelUtil.ROOT,levelMap);
        return root;
    }
    private void aclTransformTree(List<AclModuleDto> dtos, String level, Multimap<String, AclModuleDto> levelMap) {
        for(int i=0;i<dtos.size();i++){
            AclModuleDto aclModuleDto = dtos.get(i);
            String nextLevel = LevelUtil.calculateLevel(level,aclModuleDto.getId());
            List<AclModuleDto> list = (List<AclModuleDto>) levelMap.get(nextLevel);
            if(CollectionUtils.isNotEmpty(list)){
                Collections.sort(list, new Comparator<AclModuleDto>() {
                    @Override
                    public int compare(AclModuleDto o1, AclModuleDto o2) {
                        return o1.getSeq()-o2.getSeq();
                    }
                });
                aclModuleDto.setAclModuleList(list);
               aclTransformTree(list,nextLevel,levelMap);
            }
        }
    }





    @Override
    public List<AclModuleDto> userAclTree(int userId){
         List<SysAcl> userAclList = coreService.getUserAclList(userId);
         List<AclDto> aclDtoList = Lists.newArrayList();
         for(SysAcl acl:userAclList){
             AclDto dto = AclDto.adapt(acl);
             dto.setChecked(true);
             dto.setHasAcl(true);
             aclDtoList.add(dto);
         }
         return aclList2Tree(aclDtoList);
    }
}
